package login

import (
	"gin-sns/app/common/github"
	"gin-sns/app/common/qq"
	"gin-sns/app/ginframe/response"
	"gin-sns/app/ginframe/token"
	"gin-sns/app/ginframe/tools"
	"gin-sns/app/ginframe/utils/gconv"
	userModel "gin-sns/app/model/module/user"
	"gin-sns/app/service/module"
	"log"

	"github.com/gin-gonic/gin"
)

type loginReq struct {
	Username string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

var LoginApi = newLoginApi()

func newLoginApi() *loginApi {
	return &loginApi{}
}

type loginApi struct {
}

// @Summary 登陆
// @Description api测试
// @Accept  json
// @Produce  json
// @Success 200 {object} model.CommonRes
// @Router /api/v1/login [post]
func (c *loginApi) Login(ctx *gin.Context) {
	u := new(loginReq)
	if err := ctx.ShouldBind(&u); err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}

	//验证用户名和密码
	if u == nil || u.Username == "" || u.Password == "" {
		response.ErrorResp(ctx).SetMsg("用户名或密码不正确").WriteJsonExit()
		return
	}

	//获取用户id
	uid := 10

	//生成token
	token, err := token.New(gconv.String(uid)).CreateToken()

	if err != nil {
		response.ErrorResp(ctx).SetMsg("signin token不正确").WriteJsonExit()
		return
	}

	//返回token
	response.SucessResp(ctx).SetData(token).WriteJsonExit()
}

// @Summary api测试
// @Description api测试
// @Accept  json
// @Produce  json
// @Success 200 {object} model.CommonRes
// @Router /api/v1/loginOut [get]
func (c *loginApi) Test(ctx *gin.Context) {
	uid, _ := ctx.Get("uid")
	response.SucessResp(ctx).SetData(uid).WriteJsonExit()
}

// 注册
func (c *loginApi) PostSignup(ctx *gin.Context) {
	u := new(userModel.SignupReq)
	if err := ctx.ShouldBind(&u); err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}

	user, err2 := module.UserService.SignUp(u.UserName, "", u.NickName, "", u.Password, u.RePassword)
	//log.Printf("SignUp: %s", err.Error())
	if err2 != nil {
		response.ErrorResp(ctx).SetMsg(err2.Error()).WriteJsonExit()
		return
	}
	user.Password = "" //not send to user
	c.GenerateLoginResult(ctx, user, u.Ref)
	return
}

// 用户名密码登录
func (c *loginApi) PostSignin(ctx *gin.Context) {
	u := new(userModel.SigninReq)
	if err := ctx.ShouldBind(&u); err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}
	log.Printf("PostSignin")
	user, err := module.UserService.SignIn(u.UserName, u.Password)
	if err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}
	user.Password = "" //not send to user
	c.GenerateLoginResult(ctx, user, u.Ref)
	return
}

// 退出登录
func (c *loginApi) GetSignout(ctx *gin.Context) {
	err := module.UsertokenService.Signout(ctx)
	if err != nil {
		tools.JsonErrorMsg(err.Error())
		return
	}
	response.SucessResp(ctx).WriteJsonExit()
	return
}

// 获取Github登录授权地址
func (c *loginApi) GetGithubAuthorize(ctx *gin.Context) {
	ref := ctx.GetString("ref")
	url := github.AuthCodeURL(map[string]string{"ref": ref})

	response.SucessResp(ctx).SetData(tools.NewEmptyRspBuilder().Put("url", url).Build()).WriteJsonExit()
	return
}

// 获取Github回调信息获取
func (c *loginApi) GetGithubCallback(ctx *gin.Context) {
	code := ctx.GetString("code")
	state := ctx.GetString("state")

	thirdAccount, err := module.ThirdaccountService.GetOrCreateByGithub(code, state)
	if err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}

	user, codeErr := module.UserService.SignInByThirdAccount(thirdAccount)
	if codeErr != nil {
		response.ErrorResp(ctx).SetMsg(codeErr.Error()).WriteJsonExit()
		return
	} else {
		c.GenerateLoginResult(ctx, user, "")
		return
	}
}

// 获取QQ登录授权地址
func (c *loginApi) GetQqAuthorize(ctx *gin.Context) {
	ref := ctx.GetString("ref")
	url := qq.AuthorizeUrl(map[string]string{"ref": ref})
	response.SucessResp(ctx).SetData(tools.NewEmptyRspBuilder().Put("url", url).Build()).WriteJsonExit()
	return
}

// 获取QQ回调信息获取
func (c *loginApi) GetQqCallback(ctx *gin.Context) {
	code := ctx.GetString("code")
	state := ctx.GetString("state")

	thirdAccount, err := module.ThirdaccountService.GetOrCreateByQQ(code, state)
	if err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}

	user, codeErr := module.UserService.SignInByThirdAccount(thirdAccount)
	if codeErr != nil {
		response.ErrorResp(ctx).SetMsg(codeErr.Error()).WriteJsonExit()
		return
	} else {
		c.GenerateLoginResult(ctx, user, "")
		return
	}
}

// user: login user, ref: 登录来源地址，需要控制登录成功之后跳转到该地址
func (c *loginApi) GenerateLoginResult(ctx *gin.Context, user *userModel.Entity, ref string) {
	token, err := module.UsertokenService.Generate(user.Id)
	if err != nil {
		response.ErrorResp(ctx).SetMsg(err.Error()).WriteJsonExit()
		return
	}
	response.SucessResp(ctx).SetData(tools.NewEmptyRspBuilder().
		Put("token", token).
		Put("user", user).
		Put("ref", ref).Build()).WriteJsonExit()
	return
}
